//package com.nuoniu.sibanyun.interceptor.sql;
//
//import java.beans.Statement;
//import java.lang.reflect.Field;
//import java.lang.reflect.Method;
//import java.sql.Connection;
//import java.util.Date;
//import java.util.Properties;
//
//import com.baomidou.mybatisplus.core.executor.MybatisCachingExecutor;
//import com.nuoniu.sibanyun.annotation.DataAuth;
//import com.nuoniu.sibanyun.common.exception.NuoNiuException;
//import com.nuoniu.sibanyun.common.reflect.ReflectUtils;
//import com.nuoniu.sibanyun.userThread.DataScope;
//import com.nuoniu.sibanyun.userThread.UserInfo;
//import com.nuoniu.sibanyun.userThread.UserThreadLocal;
//import lombok.extern.log4j.Log4j2;
//import org.apache.commons.lang3.StringUtils;
//import org.apache.ibatis.binding.MapperMethod.ParamMap;
//import org.apache.ibatis.executor.Executor;
//import org.apache.ibatis.executor.statement.RoutingStatementHandler;
//import org.apache.ibatis.executor.statement.StatementHandler;
//import org.apache.ibatis.mapping.BoundSql;
//import org.apache.ibatis.mapping.MappedStatement;
//import org.apache.ibatis.mapping.SqlCommandType;
//import org.apache.ibatis.plugin.Interceptor;
//import org.apache.ibatis.plugin.Intercepts;
//import org.apache.ibatis.plugin.Invocation;
//import org.apache.ibatis.plugin.Plugin;
//import org.apache.ibatis.plugin.Signature;
//import org.apache.ibatis.reflection.DefaultReflectorFactory;
//import org.apache.ibatis.reflection.MetaObject;
//import org.apache.ibatis.reflection.SystemMetaObject;
//import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
//import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
//import org.apache.ibatis.session.ResultHandler;
//import org.apache.ibatis.session.RowBounds;
//import org.springframework.stereotype.Component;
//
///**
// * mybatis拦截器
// */
//@Log4j2
//@Component
//@Intercepts({
//        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}),
////        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
////        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class,
////                RowBounds.class, ResultHandler.class})
//})
//public class MybatisInterceptor implements Interceptor {
//
//
//
//    @Override
//    public Object intercept(Invocation invocation) throws Throwable {
//        UserInfo userInfo = UserThreadLocal.get();
//
//        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
//        //通过MetaObject优雅访问对象的属性，这里是访问statementHandler的属性;：MetaObject是Mybatis提供的一个用于方便、
//        //优雅访问对象属性的对象，通过它可以简化代码、不需要try/catch各种reflect异常，同时它支持对JavaBean、Collection、Map三种类型对象的操作。
//        MetaObject metaObject = MetaObject
//                .forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY,
//                        new DefaultReflectorFactory());
//        //先拦截到RoutingStatementHandler，里面有个StatementHandler类型的delegate变量，其实现类是BaseStatementHandler，然后就到BaseStatementHandler的成员变量mappedStatement
//        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
//        DataAuth dataAuth = getPermissionByDelegate(mappedStatement);
//        if (null == dataAuth  || null == userInfo || userInfo.getUserName().equals("system")) {
//            return invocation.proceed();
//        }
//        //id为执行的mapper方法的全路径名，如com.uv.dao.UserMapper.insertUser
//        String id = mappedStatement.getId();
//        //sql语句类型 select、delete、insert、update
//        String sqlCommandType = mappedStatement.getSqlCommandType().toString();
//        //数据库连接信息
////        Configuration configuration = mappedStatement.getConfiguration();
////        ComboPooledDataSource dataSource = (ComboPooledDataSource)configuration.getEnvironment().getDataSource();
////        dataSource.getJdbcUrl();
//
//        BoundSql boundSql = statementHandler.getBoundSql();
//        //获取到原始sql语句
//        String sql = boundSql.getSql();
//
//        String sqlId = mappedStatement.getId();
////        log.debug("------sqlId------" + sqlId);
//        Object parameter = invocation.getArgs()[1];
////        log.debug("------sqlCommandType------" + sqlCommandType);
//        // 获取方法上的数据权限注解，如果没有注解，则直接通过
//
//        //sql处理逻辑 + SQL替换
//        String mSql = this.permissionSql(sql, parameter, dataAuth);
//        //通过反射修改sql语句
//        Field field = boundSql.getClass().getDeclaredField("sql");
//        field.setAccessible(true);
//        field.set(boundSql, mSql);
//
//        return invocation.proceed();
//    }
//
//    @Override
//    public Object plugin(Object target) {
//        return Plugin.wrap(target, this);
//    }
//
//    @Override
//    public void setProperties(Properties properties) {
//        // TODO Auto-generated method stub
//    }
//
//    /**
//     * 获取数据权限注解信息
//     *
//     * @param mappedStatement
//     * @return
//     */
//    private DataAuth getPermissionByDelegate(MappedStatement mappedStatement) {
//        DataAuth dataAuth = null;
//        try {
//            String id = mappedStatement.getId();
//            String className = id.substring(0, id.lastIndexOf("."));
//            String methodName = id.substring(id.lastIndexOf(".") + 1, id.length());
//            final Class<?> cls = Class.forName(className);
//            final Method[] method = cls.getMethods();
//            for (Method me : method) {
//                if (me.getName().equals(methodName) && me.isAnnotationPresent(DataAuth.class)) {
//                    dataAuth = me.getAnnotation(DataAuth.class);
//                }
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return dataAuth;
//    }
//
//    /**
//     * 数据权限sql包装
//     * @param sql
//     * @return
//     */
//    private String permissionSql(String sql,Object parameter,DataAuth dataAuth){
//        String tableAlias = dataAuth.tableAlias();
//        String companyField = dataAuth.companyField();
//        String officeField = dataAuth.officeField();
//        String personalField = dataAuth.personalField();
//        UserInfo userInfo = UserThreadLocal.get();
//        DataScope dataScope = userInfo.getDataScope();
//       if( !sql.contains("WHERE")){
//           String randomStr = com.nuoniu.sibanyun.common.lang.StringUtils.getRandomStr(3);
//           String randomNum = com.nuoniu.sibanyun.common.lang.StringUtils.getRandomNum(5);
//           String errCode = randomStr + randomNum;
//           log.error("数据权限SQL拦截器错误({})，必须带where关键字",errCode);
//           throw new NuoNiuException("系统错误("+ errCode +")：请联系管理员");
//       }
//        //1.根据where关键字切分SQL
//        String[] sqlSplit = sql.split("WHERE");
//        String fromSql = sqlSplit[0];
//        if(null != dataScope.getType() && dataScope.getType() == 3){
//            fromSql += " WHERE " + tableAlias + "." + companyField + " = " + dataScope.getCompanyId();
//        }else {
//            boolean haveWhere = false;
//            if(StringUtils.isNotBlank(dataScope.getOfficeIds())){
//                haveWhere = true;
//                fromSql += " WHERE " + tableAlias + "." + officeField + " IN( " + dataScope.getOfficeIds() + ")";
//            }
//            if(StringUtils.isNotBlank(dataScope.getUserIds())){
//                String where = " WHERE ";
//                if(haveWhere)where = " AND ";
//                fromSql += where + tableAlias + "." + personalField + " IN( " + dataScope.getUserIds() + ")";
//            }
//        }
//        String resultSql = fromSql;
//        if(sqlSplit.length > 1){
//            resultSql += " AND " + sqlSplit[1];
//        }
//        return resultSql;
//    }
//}
